﻿using QntPlatform;
using QntPlatform.Strategy;
using QntPlatform.Strategy.CmdCtrl;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using QntPlatform.Model;
using QntPlatform.Db;
using QntPlatform.BinanceApi;
using QntPlatform.Strategy.S2;
using QntPlatform.Platform;

namespace QntPlatform
{
    public  class Robot:IDisposable
    {
       internal   IDictionary<string, object> context=new ConcurrentDictionary<string, object>();
        static IDictionary<long, Robot> robotDic = new ConcurrentDictionary<long, Robot>();
        ILog log= Log.GetLogger(typeof(Robot));
        public static Robot GetDicRobot(long id) {
            if (robotDic.TryGetValue(id, out var robot))
            {
              
                return robot;
            }
            return null;
        }
        public static Robot[] GetRobots()
        {
             return  robotDic.Values.ToArray();
        }


        public void OnCmdHandle(string cmd)
        {
            if (isRun)
            {
                try
                {
                    SysFun.OnCmdHandle(cmd);
                }
                catch (Exception ex)
                {
                    log.Error(ex);
                    throw;
                }
            }
            
        }
        public Robot(long id, IExchange exchange) {
            Id = id;
            Exchange = exchange;
            SysApi = QntPlatform.SysApi.Api;
            SysFun = new ISysFun(this);
            TAFun = new TAFun();
        }
        StrategyStore strategyStore = new StrategyStore();
        public RobotInfo RobotInfo { get;private set; }
        public Type strategyType;
        Dictionary<string, string> Settings;
        public Robot(RobotInfo info, Dictionary<string, string> settings = null)
        {
            log = new RobotLog(info.Id) { LogType="robot" };
            var strategyInfo = strategyStore.GetList().FirstOrDefault(p => p.Id == info.strategyId);
            strategyType = Type.GetType(strategyInfo.ContentType);

            var exchange =GetExchange(info.ExchangeId,info.Pair) ;//new BinanceExchangeImp(info.Key, info.SKey, info.Pair);
            Name = info.Name;
            Id = info.Id;
            Exchange = exchange;
            SysApi = QntPlatform.SysApi.Api;
            SysFun = new ISysFun(this);
            TAFun = new TAFun();
            Settings = info.GetStrategyArgsByStr();
            RobotInfo = info;
        }
        public IExchange GetExchange(string exchangeId,string pair)
        {
            var mng=new MngBase<ExchangeInfo>();
            var ehInfo= mng.GetById(exchangeId);
            if(ehInfo.PlatformSign=="Binance"|| ehInfo.PlatformSign == "Binance_USDT")
            {
                return new BinanceExchangeImp(ehInfo.AccessKey,ehInfo.SecretKey, pair,log);
            }
            else if(ehInfo.PlatformSign == "Binance_USD")
            {
                return new BinanceApi.DApi.USDExchangeImp(ehInfo.AccessKey, ehInfo.SecretKey, pair, log);
            }
            throw new ArgumentException($"无法处理的交易所类型:{exchangeId},{ehInfo.PlatformSign}");
        }
        
        public string Name { get; set; }
        public long Id { get; }
        public IExchange Exchange { get; }
        public ISysApi SysApi { get; }
        public ISysFun SysFun { get; }
        public TAFun TAFun { get; set; }
        public StrategyBase2 strategy;
        bool isRun = false;
      public  void Run() {
            //应在单独线程上运行
            Exception exInfo = null;
            try
            {
                //strategy = new TvCmdHandler(Exchange,SysFun,SysApi, TAFun);
                strategy=  Activator.CreateInstance(strategyType) as StrategyBase2;
              //  strategy = new CmdHandler(Exchange, SysFun, SysApi, TAFun);
                robotDic.Add(Id, this);
                SysFun.Init();
                isRun = true;
                strategy.SysInit(Exchange, SysFun, SysApi, TAFun, Settings,log);
                strategy.Init();
                strategy.MainFun();
                log.Info("启动完毕:"+Id);
            }
            catch (Exception ex)
            {
                exInfo = ex;
                log.Error(ex);
                Stop(ex);
            }
            //Stop(exInfo);
          
        }

        void Stop(Exception ex)
        {
            strategy.OnExit(ex);
            isRun = false;
            robotDic.Remove(Id);
            log.Info("机器人停止运行：" + Id);
        }

        public void Dispose()
        {
            if (isRun)
            {
                Stop(null);
            }
        }
    }
}
